package cn.yangliu.nacos.management.service.sys.impl;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static cn.yangliu.nacos.management.constant.CacheConstants.AUTHORITY_CACHE;

import cn.yangliu.jpa.base.service.impl.JpaServiceImpl;
import cn.yangliu.nacos.comm.enums.GlobalResultCode;
import cn.yangliu.nacos.comm.ex.GlobalException;
import cn.yangliu.nacos.comm.model.Oauth2InsertModel;
import cn.yangliu.nacos.comm.model.Oauth2UpdateOtherModel;
import cn.yangliu.nacos.comm.model.Oauth2UpdateOtherPasswordModel;
import cn.yangliu.nacos.comm.model.Oauth2UserModel;
import cn.yangliu.nacos.comm.oauth.Oauth2Service;
import cn.yangliu.nacos.management.entity.sys.Role;
import cn.yangliu.nacos.management.entity.sys.User;
import cn.yangliu.nacos.management.model.UserUpdateModel;
import cn.yangliu.nacos.management.repository.sys.RoleRepository;
import cn.yangliu.nacos.management.repository.sys.User2RoleRepository;
import cn.yangliu.nacos.management.repository.sys.UserRepository;
import cn.yangliu.nacos.management.service.sys.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

/**
 * The type of nacos.
 *
 * @author 问道于盲
 * @date 2020 -01-01
 */
@Service
public class UserServiceImpl extends JpaServiceImpl<User, Long, UserRepository> implements UserService {

    /**
     * current class instance's member.
     * The Oauth 2 service.
     */
    @Autowired
    private Oauth2Service oauth2Service;

    /**
     * current class instance's member.
     * The User 2 role repository.
     */
    @Autowired
    private User2RoleRepository user2RoleRepository;

    /**
     * current class instance's member.
     * The Role repository.
     */
    @Autowired
    private RoleRepository roleRepository;

    /**
     * Insert oauth 2 user model.
     *
     * @param model the model
     * @param token the token
     * @return the oauth 2 user model
     */
    @Override
    public Oauth2UserModel insert(Oauth2InsertModel model, String token) {
        return oauth2Service.insert(model, token);
    }

    /**
     * Update other oauth 2 user model.
     *
     * @param model the model
     * @param token the token
     * @return the oauth 2 user model
     */
    @Override
    public Oauth2UserModel updateOther(Oauth2UpdateOtherModel model, String token) {
        return oauth2Service.updateOther(model, token);
    }

    /**
     * Update other password boolean.
     *
     * @param model the model
     * @param token the token
     * @return the boolean
     */
    @Override
    public boolean updateOtherPassword(Oauth2UpdateOtherPasswordModel model, String token) {
        Optional<User> optional = repository.findById(model.getId());
        if (!optional.isPresent()) {
            throw new GlobalException(GlobalResultCode.DATA_NOT_EXIST);
        }
        User user = optional.get();
        model.setId(user.getOauth2Id());
        return oauth2Service.updateOtherPassword(model, token);
    }

    /**
     * Update roles user.
     *
     * @param model the model
     * @return the user
     */
    @Override
    @CacheEvict(cacheNames = AUTHORITY_CACHE, allEntries = true)
    public User updateRoles(UserUpdateModel model) {
        Optional<User> optional = repository.findById(model.getId());
        if (!optional.isPresent()) {
            throw new GlobalException(GlobalResultCode.DATA_NOT_EXIST);
        }
        User user = optional.get();

        List<Role> roles = roleRepository.findAllById(model.getRoleIds());
        user.setRoles(roles);
        return save(user);
    }

    /**
     * Store.
     *
     * @param Oauth2UserModel the oauth 2 user model
     */
    @Override
    public void store(Oauth2UserModel Oauth2UserModel) {
        String username = Oauth2UserModel.getUsername();
        User user = repository.findByUsername(username);
        if (Objects.nonNull(user)) {
            return;
        }
        user = new User();
        user.setOauth2Id(Oauth2UserModel.getId());
        user.setUsername(username);

        repository.save(user);
    }

    /**
     * Delete by id.
     *
     * @param id the id
     */
    @Override
    @CacheEvict(cacheNames = AUTHORITY_CACHE, allEntries = true)
    public void deleteById(Long id) {
        user2RoleRepository.deleteByUserId(id);
        super.deleteById(id);
    }
}
